home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / PcodeObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  26.7 KB  |  788 lines  |  [TEXT/KAHL]

  1. /* PcodeObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define SHOW_ME_OPCODEREC  /* we want to see the definition for OpcodeRec */
  31. #include "PcodeObject.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34.  
  35.  
  36. #if DEBUG
  37.     #define MINPCODEARRAYLENGTH (4) /* ridiculously small for debugging */
  38. #else
  39.     #define MINPCODEARRAYLENGTH (128)
  40. #endif
  41.  
  42.  
  43. struct PcodeRec
  44.     {
  45.         OpcodeRec*            OpcodeArray;
  46.         long                        NumInstructions;
  47.         long                        MaxArrayLength;
  48.     };
  49.  
  50.  
  51. PcodeRec*                    NewPcode(void)
  52.     {
  53.         PcodeRec*                Pcode;
  54.  
  55.         Pcode = (PcodeRec*)AllocPtrCanFail(sizeof(PcodeRec),"PcodeRec");
  56.         if (Pcode == NIL)
  57.             {
  58.              FailurePoint1:
  59.                 return NIL;
  60.             }
  61.         Pcode->OpcodeArray = (OpcodeRec*)AllocPtrCanFail(MINPCODEARRAYLENGTH
  62.             * sizeof(OpcodeRec),"OpcodeRec");
  63.         if (Pcode->OpcodeArray == NIL)
  64.             {
  65.              FailurePoint2:
  66.                 ReleasePtr((char*)Pcode);
  67.                 goto FailurePoint1;
  68.             }
  69.         Pcode->NumInstructions = 0;
  70.         Pcode->MaxArrayLength = MINPCODEARRAYLENGTH;
  71.         return Pcode;
  72.     }
  73.  
  74.  
  75. static MyBoolean    ExtendPcodeLength(PcodeRec* Pcode)
  76.     {
  77.         CheckPtrExistence(Pcode);
  78.         if (Pcode->NumInstructions == Pcode->MaxArrayLength)
  79.             {
  80.                 long                        NewLength;
  81.                 OpcodeRec*            NewVector;
  82.  
  83.                 NewLength = Pcode->MaxArrayLength * 2 + 1;
  84.                 NewVector = (OpcodeRec*)ResizePtr((char*)Pcode->OpcodeArray,
  85.                     NewLength * sizeof(OpcodeRec));
  86.                 if (NewVector == NIL)
  87.                     {
  88.                         /* failed */
  89.                         return False;
  90.                     }
  91.                 Pcode->OpcodeArray = NewVector;
  92.                 Pcode->MaxArrayLength = NewLength;
  93.             }
  94.         return True;
  95.     }
  96.  
  97.  
  98. void                            DisposePcode(PcodeRec* Pcode)
  99.     {
  100.         long                        Scan;
  101.         long                        Limit;
  102.  
  103.         CheckPtrExistence(Pcode);
  104.         Limit = Pcode->NumInstructions;
  105.         Scan = 0;
  106.         while (Scan < Limit)
  107.             {
  108.                 switch (Pcode->OpcodeArray[Scan].Opcode)
  109.                     {
  110.                         case epFuncCallUnresolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  111.                         case epFuncCallResolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  112.                             if (Scan + 1 < Limit)
  113.                                 {
  114.                                     /* conditional needed since it's possible they could have had an */
  115.                                     /* error before they got a chance to put the operands */
  116.                                     ReleasePtr(Pcode->OpcodeArray[Scan + 1].ImmediateString);
  117.                                 }
  118.                             if (Scan + 2 < Limit)
  119.                                 {
  120.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 2].DataTypeArray));
  121.                                 }
  122.                             Scan += 5;
  123.                             break;
  124.                         case epErrorTrap: /* <opcode> ^"<errorstring>" */
  125.                             if (Scan + 1 < Limit)
  126.                                 {
  127.                                     ReleasePtr(Pcode->OpcodeArray[Scan + 1].ImmediateString);
  128.                                 }
  129.                             Scan += 2;
  130.                             break;
  131.                         case epOperationBooleanEqual: /* <opcode> */
  132.                         case epOperationBooleanNotEqual:
  133.                         case epOperationBooleanAnd:
  134.                         case epOperationBooleanOr:
  135.                         case epOperationBooleanNot:
  136.                         case epOperationBooleanToInteger:
  137.                         case epOperationBooleanToFloat:
  138.                         case epOperationBooleanToDouble:
  139.                         case epOperationBooleanToFixed:
  140.                         case epOperationIntegerAdd:
  141.                         case epOperationIntegerSubtract:
  142.                         case epOperationIntegerNegation:
  143.                         case epOperationIntegerMultiply:
  144.                         case epOperationIntegerDivide:
  145.                         case epOperationIntegerModulo:
  146.                         case epOperationIntegerShiftLeft:
  147.                         case epOperationIntegerShiftRight:
  148.                         case epOperationIntegerGreaterThan:
  149.                         case epOperationIntegerLessThan:
  150.                         case epOperationIntegerGreaterThanOrEqual:
  151.                         case epOperationIntegerLessThanOrEqual:
  152.                         case epOperationIntegerEqual:
  153.                         case epOperationIntegerNotEqual:
  154.                         case epOperationIntegerAbs:
  155.                         case epOperationIntegerToBoolean:
  156.                         case epOperationIntegerToFloat:
  157.                         case epOperationIntegerToDouble:
  158.                         case epOperationIntegerToFixed:
  159.                         case epOperationFloatAdd:
  160.                         case epOperationFloatSubtract:
  161.                         case epOperationFloatNegation:
  162.                         case epOperationFloatMultiply:
  163.                         case epOperationFloatDivide:
  164.                         case epOperationFloatGreaterThan:
  165.                         case epOperationFloatLessThan:
  166.                         case epOperationFloatGreaterThanOrEqual:
  167.                         case epOperationFloatLessThanOrEqual:
  168.                         case epOperationFloatEqual:
  169.                         case epOperationFloatNotEqual:
  170.                         case epOperationFloatAbs:
  171.                         case epOperationFloatToBoolean:
  172.                         case epOperationFloatToInteger:
  173.                         case epOperationFloatToDouble:
  174.                         case epOperationFloatToFixed:
  175.                         case epOperationDoubleAdd:
  176.                         case epOperationDoubleSubtract:
  177.                         case epOperationDoubleNegation:
  178.                         case epOperationDoubleMultiply:
  179.                         case epOperationDoubleDivide:
  180.                         case epOperationDoubleGreaterThan:
  181.                         case epOperationDoubleLessThan:
  182.                         case epOperationDoubleGreaterThanOrEqual:
  183.                         case epOperationDoubleLessThanOrEqual:
  184.                         case epOperationDoubleEqual:
  185.                         case epOperationDoubleNotEqual:
  186.                         case epOperationDoubleAbs:
  187.                         case epOperationDoubleToBoolean:
  188.                         case epOperationDoubleToInteger:
  189.                         case epOperationDoubleToFloat:
  190.                         case epOperationDoubleToFixed:
  191.                         case epOperationDoubleSin:
  192.                         case epOperationDoubleCos:
  193.                         case epOperationDoubleTan:
  194.                         case epOperationDoubleAtan:
  195.                         case epOperationDoubleLn:
  196.                         case epOperationDoubleExp:
  197.                         case epOperationDoubleSqrt:
  198.                         case epOperationDoublePower:
  199.                         case epOperationFixedAdd:
  200.                         case epOperationFixedSubtract:
  201.                         case epOperationFixedNegation:
  202.                         case epOperationFixedMultiply:
  203.                         case epOperationFixedDivide:
  204.                         case epOperationFixedShiftLeft:
  205.                         case epOperationFixedShiftRight:
  206.                         case epOperationFixedGreaterThan:
  207.                         case epOperationFixedLessThan:
  208.                         case epOperationFixedGreaterThanOrEqual:
  209.                         case epOperationFixedLessThanOrEqual:
  210.                         case epOperationFixedEqual:
  211.                         case epOperationFixedNotEqual:
  212.                         case epOperationFixedAbs:
  213.                         case epOperationFixedToBoolean:
  214.                         case epOperationFixedToInteger:
  215.                         case epOperationFixedToFloat:
  216.                         case epOperationFixedToDouble:
  217.                         case epGetBooleanArraySize: /* <opcode> */
  218.                         case epGetIntegerArraySize:
  219.                         case epGetFloatArraySize:
  220.                         case epGetDoubleArraySize:
  221.                         case epGetFixedArraySize:
  222.                         case epReturnFromSubroutine: /* <opcode> */
  223.                         case epLoadImmediateNILArray: /* <opcode> */
  224.                         case epMakeBooleanArray: /* <opcode> */
  225.                         case epMakeIntegerArray:
  226.                         case epMakeFloatArray:
  227.                         case epMakeDoubleArray:
  228.                         case epMakeFixedArray:
  229.                         case epStackPop: /* <opcode> */
  230.                         case epDuplicate: /* <opcode> */
  231.                         case epNop: /* <opcode> */
  232.                         case epStackAllocate: /* <opcode> */
  233.                         case epResizeBooleanArray2: /* <opcode> */
  234.                         case epResizeIntegerArray2:
  235.                         case epResizeFloatArray2:
  236.                         case epResizeDoubleArray2:
  237.                         case epResizeFixedArray2:
  238.                         case epStoreBooleanIntoArray2: /* <opcode> */
  239.                         case epStoreIntegerIntoArray2:
  240.                         case epStoreFloatIntoArray2:
  241.                         case epStoreDoubleIntoArray2:
  242.                         case epStoreFixedIntoArray2:
  243.                         case epLoadBooleanFromArray2: /* <opcode> */
  244.                         case epLoadIntegerFromArray2:
  245.                         case epLoadFloatFromArray2:
  246.                         case epLoadDoubleFromArray2:
  247.                         case epLoadFixedFromArray2:
  248.                         case epOperationBooleanXor:
  249.                         case epOperationIntegerAnd:
  250.                         case epOperationFixedAnd:
  251.                         case epOperationIntegerOr:
  252.                         case epOperationFixedOr:
  253.                         case epOperationIntegerXor:
  254.                         case epOperationFixedXor:
  255.                         case epOperationIntegerImpreciseDivide:
  256.                         case epOperationFloatShiftLeft:
  257.                         case epOperationDoubleShiftLeft:
  258.                         case epOperationFloatShiftRight:
  259.                         case epOperationDoubleShiftRight:
  260.                         case epOperationIntegerNot:
  261.                         case epOperationDoubleAsin:
  262.                         case epOperationDoubleAcos:
  263.                         case epOperationDoubleSqr:
  264.                         case epOperationTestIntegerNegative:
  265.                         case epOperationTestFloatNegative:
  266.                         case epOperationTestDoubleNegative:
  267.                         case epOperationTestFixedNegative:
  268.                         case epOperationGetSignInteger:
  269.                         case epOperationGetSignFloat:
  270.                         case epOperationGetSignDouble:
  271.                         case epOperationGetSignFixed:
  272.                             Scan += 1;
  273.                             break;
  274.                         case epStackPopMultiple: /* <opcode> <numwords> */
  275.                         case epStackDeallocateUnder: /* <opcode> <numwords> */
  276.                         case epOperationBooleanToIntegerBuried:  /* <opcode> <stackindex> */
  277.                         case epOperationBooleanToFloatBuried:
  278.                         case epOperationBooleanToDoubleBuried:
  279.                         case epOperationBooleanToFixedBuried:
  280.                         case epOperationIntegerToBooleanBuried:
  281.                         case epOperationIntegerToFloatBuried:
  282.                         case epOperationIntegerToDoubleBuried:
  283.                         case epOperationIntegerToFixedBuried:
  284.                         case epOperationFloatToBooleanBuried:
  285.                         case epOperationFloatToIntegerBuried:
  286.                         case epOperationFloatToDoubleBuried:
  287.                         case epOperationFloatToFixedBuried:
  288.                         case epOperationDoubleToBooleanBuried:
  289.                         case epOperationDoubleToIntegerBuried:
  290.                         case epOperationDoubleToFloatBuried:
  291.                         case epOperationDoubleToFixedBuried:
  292.                         case epOperationFixedToBooleanBuried:
  293.                         case epOperationFixedToIntegerBuried:
  294.                         case epOperationFixedToFloatBuried:
  295.                         case epOperationFixedToDoubleBuried:
  296.                         case epBranchUnconditional: /* <opcode> <branchoffset> */
  297.                         case epBranchIfZero:
  298.                         case epBranchIfNotZero:
  299.                         case epStoreIntegerOnStack: /* <opcode> <stackindex> */
  300.                         case epStoreFloatOnStack:
  301.                         case epStoreDoubleOnStack:
  302.                         case epStoreArrayOnStack:
  303.                         case epLoadIntegerFromStack:
  304.                         case epLoadFloatFromStack:
  305.                         case epLoadDoubleFromStack:
  306.                         case epLoadArrayFromStack:
  307.                         case epLoadImmediateInteger: /* <opcode> <integer>; also used for boolean & fixed */
  308.                             Scan += 2;
  309.                             break;
  310.                         case epLoadImmediateFloat: /* <opcode> ^<float> */
  311.                             if (Scan + 1 < Limit)
  312.                                 {
  313.                                     /* conditional needed since it's possible they could have had an */
  314.                                     /* error before they got a chance to put the operands */
  315.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 1].ImmediateFloat));
  316.                                 }
  317.                             Scan += 2;
  318.                             break;
  319.                         case epLoadImmediateDouble: /* <opcode> ^<double> */
  320.                             if (Scan + 1 < Limit)
  321.                                 {
  322.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 1].ImmediateDouble));
  323.                                 }
  324.                             Scan += 2;
  325.                             break;
  326.                         case epGetSampleLeftArray: /* <opcode> ^"<namestring>" */
  327.                         case epGetSampleRightArray:
  328.                         case epGetSampleMonoArray:
  329.                         case epGetWaveTableArray:
  330.                         case epGetWaveTableFrames:
  331.                         case epGetWaveTableTables:
  332.                             if (Scan + 1 < Limit)
  333.                                 {
  334.                                     ReleasePtr((char*)(Pcode->OpcodeArray[Scan + 1].ImmediateString));
  335.                                 }
  336.                             Scan += 2;
  337.                             break;
  338.                         default:
  339.                             EXECUTE(PRERR(ForceAbort,"DisposePcode:  unknown opcode"));
  340.                             break;
  341.                     }
  342.             }
  343.         ReleasePtr((char*)(Pcode->OpcodeArray));
  344.         ReleasePtr((char*)Pcode);
  345.     }
  346.  
  347.  
  348. long                            PcodeGetNextAddress(PcodeRec* Pcode)
  349.     {
  350.         CheckPtrExistence(Pcode);
  351.         return Pcode->NumInstructions;
  352.     }
  353.  
  354.  
  355. OpcodeRec*                GetOpcodeFromPcode(PcodeRec* Pcode)
  356.     {
  357.         CheckPtrExistence(Pcode);
  358.         return Pcode->OpcodeArray;
  359.     }
  360.  
  361.  
  362. /* get the number of cells in the array */
  363. long                            GetNumberOfValidCellsInPcode(PcodeRec* Pcode)
  364.     {
  365.         CheckPtrExistence(Pcode);
  366.         return Pcode->NumInstructions;
  367.     }
  368.  
  369.  
  370. /* put a new opcode array into the pcode.  this does not allocate or release any */
  371. /* memory, but merely updates the pointer.  it should not be called by anyone */
  372. /* except the optimizer.   after the optimizer is done, it resizes the array to */
  373. /* be exactly the size we need. */
  374. void                            UpdateOpcodeInPcode(PcodeRec* Pcode, OpcodeRec* NewOpcodeArray,
  375.                                         long NewNumInstructions)
  376.     {
  377.         CheckPtrExistence(Pcode);
  378.         CheckPtrExistence(NewOpcodeArray);
  379.         ERROR((NewNumInstructions < 0) || (NewNumInstructions
  380.             > PtrSize((char*)NewOpcodeArray) / sizeof(OpcodeRec)),PRERR(ForceAbort,
  381.             "UpdateOpcodeInPcode:  bad array size problem"));
  382.         Pcode->OpcodeArray = NewOpcodeArray;
  383.         Pcode->NumInstructions = NewNumInstructions;
  384.     }
  385.  
  386.  
  387. /* Add a pcode instruction.  *Index returns the index of the instruction so that */
  388. /* branches can be patched up.  if Index is NIL, then it won't bother returning */
  389. /* anything. */
  390. MyBoolean                    AddPcodeInstruction(PcodeRec* Pcode, Pcodes Opcode, long* Index)
  391.     {
  392.         CheckPtrExistence(Pcode);
  393.         if (!ExtendPcodeLength(Pcode))
  394.             {
  395.                 return False;
  396.             }
  397.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  398.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  399.         Pcode->OpcodeArray[Pcode->NumInstructions].Opcode = Opcode;
  400.         if (Index != NIL)
  401.             {
  402.                 *Index = Pcode->NumInstructions;
  403.             }
  404.         Pcode->NumInstructions += 1;
  405.         return True;
  406.     }
  407.  
  408.  
  409. MyBoolean                    AddPcodeOperandDouble(PcodeRec* Pcode, double ImmediateData)
  410.     {
  411.         double*                    NewDouble;
  412.  
  413.         CheckPtrExistence(Pcode);
  414.         if (!ExtendPcodeLength(Pcode))
  415.             {
  416.                 return False;
  417.             }
  418.         NewDouble = (double*)AllocPtrCanFail(sizeof(double),"PcodeDouble");
  419.         if (NewDouble == NIL)
  420.             {
  421.                 return False;
  422.             }
  423.         *NewDouble = ImmediateData;
  424.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  425.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  426.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateDouble = NewDouble;
  427.         Pcode->NumInstructions += 1;
  428.         return True;
  429.     }
  430.  
  431.  
  432. MyBoolean                    AddPcodeOperandFloat(PcodeRec* Pcode, float ImmediateData)
  433.     {
  434.         float*                    NewFloat;
  435.  
  436.         CheckPtrExistence(Pcode);
  437.         if (!ExtendPcodeLength(Pcode))
  438.             {
  439.                 return False;
  440.             }
  441.         NewFloat = (float*)AllocPtrCanFail(sizeof(float),"PcodeFloat");
  442.         if (NewFloat == NIL)
  443.             {
  444.                 return False;
  445.             }
  446.         *NewFloat = ImmediateData;
  447.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  448.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  449.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateFloat = NewFloat;
  450.         Pcode->NumInstructions += 1;
  451.         return True;
  452.     }
  453.  
  454.  
  455. MyBoolean                    AddPcodeOperandInteger(PcodeRec* Pcode, long ImmediateData)
  456.     {
  457.         CheckPtrExistence(Pcode);
  458.         if (!ExtendPcodeLength(Pcode))
  459.             {
  460.                 return False;
  461.             }
  462.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  463.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  464.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateInteger = ImmediateData;
  465.         Pcode->NumInstructions += 1;
  466.         return True;
  467.     }
  468.  
  469.  
  470. /* the string must be null terminated */
  471. MyBoolean                    AddPcodeOperandString(PcodeRec* Pcode, char* String, long Length)
  472.     {
  473.         char*                        NewString;
  474.  
  475.         CheckPtrExistence(Pcode);
  476.         if (!ExtendPcodeLength(Pcode))
  477.             {
  478.                 return False;
  479.             }
  480.         NewString = AllocPtrCanFail(Length + 1,"PcodeString");
  481.         if (NewString == NIL)
  482.             {
  483.                 return False;
  484.             }
  485.         CopyData(String,NewString,Length);
  486.         NewString[Length] = 0; /* null termination */
  487.  
  488.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  489.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  490.         Pcode->OpcodeArray[Pcode->NumInstructions].ImmediateString = NewString;
  491.         Pcode->NumInstructions += 1;
  492.         return True;
  493.     }
  494.  
  495.  
  496. MyBoolean                    AddPcodeOperandDataTypeArray(PcodeRec* Pcode, DataTypes* DataTypeArray)
  497.     {
  498.         DataTypes*            NewTypeArray;
  499.  
  500.         CheckPtrExistence(Pcode);
  501.         if (!ExtendPcodeLength(Pcode))
  502.             {
  503.                 return False;
  504.             }
  505.         NewTypeArray = (DataTypes*)CopyPtr((char*)DataTypeArray);
  506.         if (NewTypeArray == NIL)
  507.             {
  508.                 return False;
  509.             }
  510.         SetTag(NewTypeArray,"PcodeDataTypeArray");
  511.  
  512.         PRNGCHK(Pcode->OpcodeArray,&(Pcode->OpcodeArray[Pcode->NumInstructions]),
  513.             sizeof(Pcode->OpcodeArray[Pcode->NumInstructions]));
  514.         Pcode->OpcodeArray[Pcode->NumInstructions].DataTypeArray = NewTypeArray;
  515.         Pcode->NumInstructions += 1;
  516.         return True;
  517.     }
  518.  
  519.  
  520. void                            ResolvePcodeBranch(PcodeRec* Pcode, long Where, long Destination)
  521.     {
  522.         CheckPtrExistence(Pcode);
  523.         ERROR((Where < 0) || (Where + 1 >= Pcode->NumInstructions),PRERR(ForceAbort,
  524.             "ResolvePcodeBranch:  address out of range"));
  525.         ERROR((Pcode->OpcodeArray[Where].Opcode != epBranchUnconditional)
  526.             && (Pcode->OpcodeArray[Where].Opcode != epBranchIfZero)
  527.             && (Pcode->OpcodeArray[Where].Opcode != epBranchIfNotZero),PRERR(ForceAbort,
  528.             "ResolvePcodeBranch:  patching a non-branch instruction"));
  529.         Pcode->OpcodeArray[Where + 1].ImmediateInteger = Destination;
  530.     }
  531.  
  532.  
  533. static MyBoolean    LocalStrEqu(char* Left, char* Right, long LeftLen, long RightLen)
  534.     {
  535.         if (LeftLen == RightLen)
  536.             {
  537.                 return MemEqu(Left,Right,LeftLen);
  538.             }
  539.         return False;
  540.     }
  541.  
  542.  
  543. void                            PcodeUnlink(PcodeRec* Function, char* DeadFuncName,
  544.                                         PcodeRec* DeadFuncCode)
  545.     {
  546.         long                        Scan;
  547.         long                        Limit;
  548.  
  549.         CheckPtrExistence(Function);
  550.         CheckPtrExistence(DeadFuncCode);
  551.         Limit = Function->NumInstructions;
  552.         Scan = 0;
  553.         while (Scan < Limit)
  554.             {
  555.                 /* first, see if we have to delink it */
  556.                 if (Function->OpcodeArray[Scan].Opcode == epFuncCallResolved)
  557.                     {
  558.                         /* this is the one we have to delink. */
  559.                         /*    0              1              2            3            4    */
  560.                         /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  561.                         /* will be converted to */
  562.                         /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  563.                         ERROR(LocalStrEqu(Function->OpcodeArray[Scan + 1].ImmediateString,
  564.                             DeadFuncName,StrLen(Function->OpcodeArray[Scan + 1].ImmediateString),
  565.                             PtrSize(DeadFuncName)) && (DeadFuncCode->OpcodeArray
  566.                             != Function->OpcodeArray[Scan + 4].FunctionOpcodeRecPtr),
  567.                             PRERR(ForceAbort,"PcodeUnlink:  found a function with the right name "
  568.                             "but it's not linked to the same code record"));
  569.                         ERROR(!LocalStrEqu(Function->OpcodeArray[Scan + 1].ImmediateString,
  570.                             DeadFuncName,StrLen(Function->OpcodeArray[Scan + 1].ImmediateString),
  571.                             PtrSize(DeadFuncName)) && (DeadFuncCode->OpcodeArray
  572.                             == Function->OpcodeArray[Scan + 4].FunctionOpcodeRecPtr),
  573.                             PRERR(ForceAbort,"PcodeUnlink:  found a function that's linked to this "
  574.                             "code record, but with a different function name"));
  575.                         if (LocalStrEqu(Function->OpcodeArray[Scan + 1].ImmediateString,
  576.                             DeadFuncName,StrLen(Function->OpcodeArray[Scan + 1].ImmediateString),
  577.                             PtrSize(DeadFuncName)))
  578.                             {
  579.                                 /* if the name is the same, then delink it */
  580.                                 Function->OpcodeArray[Scan].Opcode = epFuncCallUnresolved;
  581.                                 Function->OpcodeArray[Scan + 4].FunctionOpcodeRecPtr = NIL;
  582.                             }
  583.                     }
  584.                 /* now, advance the program counter the right amount */
  585.                 Scan += GetInstructionLength(Function->OpcodeArray[Scan].Opcode);
  586.             }
  587.     }
  588.  
  589.  
  590. long                            GetInstructionLength(Pcodes OpcodeWord)
  591.     {
  592.         switch (OpcodeWord)
  593.             {
  594.                 case epFuncCallUnresolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  595.                 case epFuncCallResolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  596.                     return 5;
  597.                 case epOperationBooleanEqual: /* <opcode> */
  598.                 case epOperationBooleanNotEqual:
  599.                 case epOperationBooleanAnd:
  600.                 case epOperationBooleanOr:
  601.                 case epOperationBooleanNot:
  602.                 case epOperationBooleanToInteger:
  603.                 case epOperationBooleanToFloat:
  604.                 case epOperationBooleanToDouble:
  605.                 case epOperationBooleanToFixed:
  606.                 case epOperationIntegerAdd:
  607.                 case epOperationIntegerSubtract:
  608.                 case epOperationIntegerNegation:
  609.                 case epOperationIntegerMultiply:
  610.                 case epOperationIntegerDivide:
  611.                 case epOperationIntegerModulo:
  612.                 case epOperationIntegerShiftLeft:
  613.                 case epOperationIntegerShiftRight:
  614.                 case epOperationIntegerGreaterThan:
  615.                 case epOperationIntegerLessThan:
  616.                 case epOperationIntegerGreaterThanOrEqual:
  617.                 case epOperationIntegerLessThanOrEqual:
  618.                 case epOperationIntegerEqual:
  619.                 case epOperationIntegerNotEqual:
  620.                 case epOperationIntegerAbs:
  621.                 case epOperationIntegerToBoolean:
  622.                 case epOperationIntegerToFloat:
  623.                 case epOperationIntegerToDouble:
  624.                 case epOperationIntegerToFixed:
  625.                 case epOperationFloatAdd:
  626.                 case epOperationFloatSubtract:
  627.                 case epOperationFloatNegation:
  628.                 case epOperationFloatMultiply:
  629.                 case epOperationFloatDivide:
  630.                 case epOperationFloatGreaterThan:
  631.                 case epOperationFloatLessThan:
  632.                 case epOperationFloatGreaterThanOrEqual:
  633.                 case epOperationFloatLessThanOrEqual:
  634.                 case epOperationFloatEqual:
  635.                 case epOperationFloatNotEqual:
  636.                 case epOperationFloatAbs:
  637.                 case epOperationFloatToBoolean:
  638.                 case epOperationFloatToInteger:
  639.                 case epOperationFloatToDouble:
  640.                 case epOperationFloatToFixed:
  641.                 case epOperationDoubleAdd:
  642.                 case epOperationDoubleSubtract:
  643.                 case epOperationDoubleNegation:
  644.                 case epOperationDoubleMultiply:
  645.                 case epOperationDoubleDivide:
  646.                 case epOperationDoubleGreaterThan:
  647.                 case epOperationDoubleLessThan:
  648.                 case epOperationDoubleGreaterThanOrEqual:
  649.                 case epOperationDoubleLessThanOrEqual:
  650.                 case epOperationDoubleEqual:
  651.                 case epOperationDoubleNotEqual:
  652.                 case epOperationDoubleAbs:
  653.                 case epOperationDoubleToBoolean:
  654.                 case epOperationDoubleToInteger:
  655.                 case epOperationDoubleToFloat:
  656.                 case epOperationDoubleToFixed:
  657.                 case epOperationDoubleSin:
  658.                 case epOperationDoubleCos:
  659.                 case epOperationDoubleTan:
  660.                 case epOperationDoubleAtan:
  661.                 case epOperationDoubleLn:
  662.                 case epOperationDoubleExp:
  663.                 case epOperationDoubleSqrt:
  664.                 case epOperationDoublePower:
  665.                 case epOperationFixedAdd:
  666.                 case epOperationFixedSubtract:
  667.                 case epOperationFixedNegation:
  668.                 case epOperationFixedMultiply:
  669.                 case epOperationFixedDivide:
  670.                 case epOperationFixedShiftLeft:
  671.                 case epOperationFixedShiftRight:
  672.                 case epOperationFixedGreaterThan:
  673.                 case epOperationFixedLessThan:
  674.                 case epOperationFixedGreaterThanOrEqual:
  675.                 case epOperationFixedLessThanOrEqual:
  676.                 case epOperationFixedEqual:
  677.                 case epOperationFixedNotEqual:
  678.                 case epOperationFixedAbs:
  679.                 case epOperationFixedToBoolean:
  680.                 case epOperationFixedToInteger:
  681.                 case epOperationFixedToFloat:
  682.                 case epOperationFixedToDouble:
  683.                 case epGetBooleanArraySize: /* <opcode> */
  684.                 case epGetIntegerArraySize:
  685.                 case epGetFloatArraySize:
  686.                 case epGetDoubleArraySize:
  687.                 case epGetFixedArraySize:
  688.                 case epReturnFromSubroutine: /* <opcode> */
  689.                 case epLoadImmediateNILArray: /* <opcode> */
  690.                 case epMakeBooleanArray: /* <opcode> */
  691.                 case epMakeIntegerArray:
  692.                 case epMakeFloatArray:
  693.                 case epMakeDoubleArray:
  694.                 case epMakeFixedArray:
  695.                 case epStackPop: /* <opcode> */
  696.                 case epDuplicate: /* <opcode> */
  697.                 case epNop: /* <opcode> */
  698.                 case epStackAllocate: /* <opcode> */
  699.                 case epResizeBooleanArray2: /* <opcode> */
  700.                 case epResizeIntegerArray2:
  701.                 case epResizeFloatArray2:
  702.                 case epResizeDoubleArray2:
  703.                 case epResizeFixedArray2:
  704.                 case epStoreBooleanIntoArray2: /* <opcode> */
  705.                 case epStoreIntegerIntoArray2:
  706.                 case epStoreFloatIntoArray2:
  707.                 case epStoreDoubleIntoArray2:
  708.                 case epStoreFixedIntoArray2:
  709.                 case epLoadBooleanFromArray2: /* <opcode> */
  710.                 case epLoadIntegerFromArray2:
  711.                 case epLoadFloatFromArray2:
  712.                 case epLoadDoubleFromArray2:
  713.                 case epLoadFixedFromArray2:
  714.                 case epOperationBooleanXor:
  715.                 case epOperationIntegerAnd:
  716.                 case epOperationFixedAnd:
  717.                 case epOperationIntegerOr:
  718.                 case epOperationFixedOr:
  719.                 case epOperationIntegerXor:
  720.                 case epOperationFixedXor:
  721.                 case epOperationIntegerImpreciseDivide:
  722.                 case epOperationFloatShiftLeft:
  723.                 case epOperationDoubleShiftLeft:
  724.                 case epOperationFloatShiftRight:
  725.                 case epOperationDoubleShiftRight:
  726.                 case epOperationIntegerNot:
  727.                 case epOperationDoubleAsin:
  728.                 case epOperationDoubleAcos:
  729.                 case epOperationDoubleSqr:
  730.                 case epOperationTestIntegerNegative:
  731.                 case epOperationTestFloatNegative:
  732.                 case epOperationTestDoubleNegative:
  733.                 case epOperationTestFixedNegative:
  734.                 case epOperationGetSignInteger:
  735.                 case epOperationGetSignFloat:
  736.                 case epOperationGetSignDouble:
  737.                 case epOperationGetSignFixed:
  738.                     return 1;
  739.                 case epStackPopMultiple: /* <opcode> <numwords> */
  740.                 case epStackDeallocateUnder: /* <opcode> <numwords> */
  741.                 case epOperationBooleanToIntegerBuried:  /* <opcode> <stackindex> */
  742.                 case epOperationBooleanToFloatBuried:
  743.                 case epOperationBooleanToDoubleBuried:
  744.                 case epOperationBooleanToFixedBuried:
  745.                 case epOperationIntegerToBooleanBuried:
  746.                 case epOperationIntegerToFloatBuried:
  747.                 case epOperationIntegerToDoubleBuried:
  748.                 case epOperationIntegerToFixedBuried:
  749.                 case epOperationFloatToBooleanBuried:
  750.                 case epOperationFloatToIntegerBuried:
  751.                 case epOperationFloatToDoubleBuried:
  752.                 case epOperationFloatToFixedBuried:
  753.                 case epOperationDoubleToBooleanBuried:
  754.                 case epOperationDoubleToIntegerBuried:
  755.                 case epOperationDoubleToFloatBuried:
  756.                 case epOperationDoubleToFixedBuried:
  757.                 case epOperationFixedToBooleanBuried:
  758.                 case epOperationFixedToIntegerBuried:
  759.                 case epOperationFixedToFloatBuried:
  760.                 case epOperationFixedToDoubleBuried:
  761.                 case epBranchUnconditional: /* <opcode> <branchoffset> */
  762.                 case epBranchIfZero:
  763.                 case epBranchIfNotZero:
  764.                 case epStoreIntegerOnStack: /* <opcode> <stackindex> */
  765.                 case epStoreFloatOnStack:
  766.                 case epStoreDoubleOnStack:
  767.                 case epStoreArrayOnStack:
  768.                 case epLoadIntegerFromStack:
  769.                 case epLoadFloatFromStack:
  770.                 case epLoadDoubleFromStack:
  771.                 case epLoadArrayFromStack:
  772.                 case epLoadImmediateInteger: /* <opcode> <integer>; also used for boolean & fixed */
  773.                 case epLoadImmediateFloat: /* <opcode> ^<float> */
  774.                 case epLoadImmediateDouble: /* <opcode> ^<double> */
  775.                 case epGetSampleLeftArray: /* <opcode> ^"<namestring>" */
  776.                 case epGetSampleRightArray:
  777.                 case epGetSampleMonoArray:
  778.                 case epGetWaveTableArray:
  779.                 case epGetWaveTableFrames:
  780.                 case epGetWaveTableTables:
  781.                 case epErrorTrap: /* <opcode> ^"<errorstring>" */
  782.                     return 2;
  783.                 default:
  784.                     EXECUTE(PRERR(ForceAbort,"GetInstructionLength:  unknown opcode"));
  785.             }
  786.         EXECUTE(PRERR(ForceAbort,"GetInstructionLength:  control reached end of function"));
  787.     }
  788.